﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.ComponentModel;
using System.Web;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using System.Collections.Specialized;

namespace WorkflowManagement.Web.UI
{
    /// <summary>
    /// The <see cref="WorkflowManager"/> provides functionality for managing workflows in page web page.
    /// </summary>
    /// <remarks>
    /// There can only be one instance of <see cref="WorkflowManager"/> running on a page.
    /// </remarks>
    /// <seealso cref="WorkflowManagerProxy"/>
    [ToolboxData("<{0}:WorkflowManager ID=\"|\" runat=\"server\"></{0}:WorkflowManager>")]
    public class WorkflowManager: WorkflowManagerBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="WorkflowManager"/> class.
        /// </summary>
        public WorkflowManager()
        {
        }

        /// <summary>
        /// Raises the System.Web.UI.Control.Init event.
        /// </summary>
        /// <param name="e">An System.EventArgs object that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            
            // Check that there are no other instances of WorkflowManager running on the page.
            WorkflowManager manager = Page.Items["WorkflowManager"] as WorkflowManager;
            if (manager != null)
                throw new InvalidOperationException(Properties.Resources.WorkflowManager_OnlyOneInstanceAllowedPerPage);
                
            // Assign a the current WorkflowManager to the page context.
            Page.Items["WorkflowManager"] = this;
        }

        /// <summary>
        /// Provides a way to retrieve the current <see cref="WorkflowManager"/>.
        /// </summary>
        /// <param name="page">The ASP.NET <see cref="System.Web.UI.Page"/> on which to find the <see cref="WorkflowManager"/>.</param>
        /// <returns>The running instance of the <see cref="WorkflowManager"/>.</returns>
        public static WorkflowManager GetCurrentWorkflowManager(Page page)
        {
            if (page == null)
                throw new ArgumentNullException("page");
                
            WorkflowManager manager = page.Items["WorkflowManager"] as WorkflowManager;
            if (manager == null)
                throw new InvalidOperationException(Properties.Resources.WorkflowManager_CannotFindWorkflowManager);
                
            return manager;
        }

        internal override void ExecuteWorkflow(Type workflowType, Dictionary<string, object> parameters)
        {
            WorkflowRuntime runtime = Page.Application["WorkflowRuntime"] as WorkflowRuntime;            
            WorkflowInstance instance = runtime.CreateWorkflow(workflowType, parameters);
            instance.Start();
            ManualWorkflowSchedulerService manualScheduler = runtime.GetService<ManualWorkflowSchedulerService>();
            manualScheduler.RunWorkflow(instance.InstanceId);            
        }

        private List<WorkflowManagerProxy> proxys = new List<WorkflowManagerProxy>();
        
        internal void RegisterProxy(WorkflowManagerProxy proxy)
        {
            if (proxy == null)
                throw new ArgumentNullException("proxy");
                
            proxys.Add(proxy);
        }
    }
}
